package com.igoal.service;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.appfuse.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.igoal.dao.NewsDAO;
import com.igoal.dao.UserActivityDAO;
import com.igoal.dao.UserGoalEntryDAO;
import com.igoal.dao.UserGoalEntryDoneDAO;
import com.igoal.dao.UserLikeDAO;
import com.igoal.dao.UserStatusDAO;
import com.igoal.dao.UserThoughtDAO;
import com.igoal.dto.UserDTO;
import com.igoal.entity.ActionTypeEnum;
import com.igoal.entity.ComponentEnum;
import com.igoal.entity.ItemOwner;
import com.igoal.entity.User;
import com.igoal.entity.UserLike;
import com.igoal.entity.factory.EntityFactory;

@Service("likeService")
public class LikeServiceImpl implements LikeService {

	private static Log logger = LogFactory.getLog(LikeService.class);

	private UserLikeDAO userLikeDAO;
	private UserDao userDao;
	private ActionLoggerService actionLoggerService;
	private UserGoalEntryDAO userGoalEntryDAO;
	private UserGoalEntryDoneDAO userGoalEntryDoneDAO;
	private UserActivityDAO userActivityDAO;
	private UserThoughtDAO userThoughtDAO;
	private UserStatusDAO userStatusDAO;
	private NewsDAO newsDAO;

	@Autowired
	public void setNewsDAO(NewsDAO newsDAO) {
		this.newsDAO = newsDAO;
	}

	@Autowired
	public void setUserLikeDAO(UserLikeDAO userLikeDAO) {
		this.userLikeDAO = userLikeDAO;
	}

	@Autowired
	public void setUserDAO(UserDao userDao) {
		this.userDao = userDao;
	}

	@Autowired
	public void setActionLoggerService(ActionLoggerService actionLoggerService) {
		this.actionLoggerService = actionLoggerService;
	}

	@Autowired
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	@Autowired
	public void setUserGoalEntryDAO(UserGoalEntryDAO userGoalEntryDAO) {
		this.userGoalEntryDAO = userGoalEntryDAO;
	}

	@Autowired
	public void setUserGoalEntryDoneDAO(UserGoalEntryDoneDAO userGoalEntryDoneDAO) {
		this.userGoalEntryDoneDAO = userGoalEntryDoneDAO;
	}

	@Autowired
	public void setUserActivityDAO(UserActivityDAO userActivityDAO) {
		this.userActivityDAO = userActivityDAO;
	}

	@Autowired
	public void setUserThoughtDAO(UserThoughtDAO userThoughtDAO) {
		this.userThoughtDAO = userThoughtDAO;
	}

	@Autowired
	public void setUserStatusDAO(UserStatusDAO userStatusDAO) {
		this.userStatusDAO = userStatusDAO;
	}

	public int likeComponent(String username, String componentName, Long componentId) {
		try {
			User user = (User) userDao.loadUserByUsername(username);
			ComponentEnum component = ComponentEnum.valueOf(componentName);
			UserLike userLike = EntityFactory.createUserLike(user, component, componentId);
			if (!userLikeDAO.isLikedThis(user.getId(), component, componentId)) {
				userLikeDAO.save(userLike);
				ItemOwner item = loadItem(componentId, component);
				actionLoggerService.log(item.getOwner(), user, ActionTypeEnum.LIKE, component, componentId);
				return SaveResult.SUCCESS;
			} else {
				logger.error("User[" + user.getUsername() + "] requested double likes.");
				return SaveResult.FAIL;
			}
		} catch (Exception e) {
			logger.error(e);
			return SaveResult.FAIL;
		}
	}

	public int unlikeComponent(String username, String componentName, Long componentId) {
		try {
			User user = (User) userDao.loadUserByUsername(username);
			ComponentEnum component = ComponentEnum.valueOf(componentName);
			UserLike userLike = userLikeDAO.findByInformation(user.getId(), component, componentId);
			if (userLike != null) {
				userLikeDAO.remove(userLike.getId());
				return SaveResult.SUCCESS;
			}
			return SaveResult.FAIL;
		} catch (Exception e) {
			logger.error(e);
			return SaveResult.FAIL;
		}
	}

	public List<UserDTO> getRandomLikeUsers(Long userId, ComponentEnum component, Long componentId) {
		List<UserLike> userLikes = userLikeDAO.getRandomeLikeList(userId, component, componentId);
		List<UserDTO> likes = new ArrayList<UserDTO>();
		for(UserLike userLike : userLikes){
			UserDTO userDTO = new UserDTO();
			userDTO.initFrom(userLike.getUser());
			likes.add(userDTO);
		}
		return likes;
	}

	public int likeCount(ComponentEnum component, Long componentId) {
		return userLikeDAO.countComponentLike(component, componentId);
	}

	public List<UserDTO> getUsersLikePerPage(ComponentEnum component, Long componenId, int pageNumber) {
		List<UserDTO> dtoList = new ArrayList<UserDTO>();
		List<UserLike> userLikeList = userLikeDAO.getUserLikedThisComponent(component, componenId, pageNumber);
		
		for (UserLike userLike : userLikeList) {
			User user = userLike.getUser();
			UserDTO dto = new UserDTO();
			dto.initFrom(user);
			dtoList.add(dto);
		}
		
		return dtoList;
	}

	/**
	 * temporarily copied from comment service
	 * 
	 * @param componentId
	 * @param component
	 * @return
	 */
	private ItemOwner loadItem(Long componentId, ComponentEnum component) {
		ItemOwner item = null;

		// TODO: remove this stupid solution when has another :(
		switch (component) {
			case DONE_ENTRY:
				item = userGoalEntryDoneDAO.get(componentId);
				break;
			case GOAL_ENTRY:
				item = userGoalEntryDAO.get(componentId);
				break;
			case USER_STATUS:
				item = userStatusDAO.get(componentId);
				break;
			case USER_THOUGHT:
				item = userThoughtDAO.get(componentId);
				break;
			case USER_ACTIVITY:
				item = userActivityDAO.get(componentId);
				break;
			case NEWS:
				item = newsDAO.get(componentId);
				break;
		}

		return item;
	}

}
